// Copyright (C) 1953-2022 NUDT
// Verilog module name - forward_mode_control
// Version: V4.0.0.20220524
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//          
///////////////////////////////////////////////////////////////////////////


module forward_mode_control
#(
    parameter NUM_GMAC = 8,  
    parameter NUM_XGMAC = 0	
)
(
        i_clk              ,   
        i_rst_n            ,
        
        i_pkt_rx_finish    ,

        iv_desp              ,
		i_desp_wr            ,	
        
        iv_fwdmoderam_addr  ,
        iv_fwdmoderam_wdata ,
        i_fwdmoderam_wr     ,
        ov_fwdmoderam_rdata ,
        i_fwdmoderam_rd     ,
        
        ov_desp              , 
        o_desp_wr            
         
);
// I/O
// clk & rst  
input               i_clk  ;
input               i_rst_n;

input      [(NUM_XGMAC + NUM_GMAC + 1)  -1:0]         i_pkt_rx_finish   ;
//5tuple & dmac input
input      [87:0]   iv_desp  ;
input               i_desp_wr;

input      [5:0]    iv_fwdmoderam_addr     ;
input      [33:0]   iv_fwdmoderam_wdata    ;
input               i_fwdmoderam_wr        ;
output     [33:0]   ov_fwdmoderam_rdata    ;
input               i_fwdmoderam_rd        ;
//tsntag & bufid output 
output     [87:0]   ov_desp  ;
output              o_desp_wr;
//***************************************************
//          extract five tuple from pkt 
//***************************************************
// internal reg&wire for state machine
wire   [5:0]        wv_ram_raddr_b_fml2ram;
wire                w_ram_rd_b_fml2ram    ;
wire   [33:0]       wv_ram_rdata_b_ram2fml;

wire   [87:0]       wv_desp_fml2fmj    ;
wire                w_desp_wr_fml2fmj  ;

wire   [87:0]       wv_desp_storedfwd_fmj2sfc          ;
wire                w_desp_wr_storedfwd_fmj2sfc        ;
wire                w_cutthroughfwd_fmj2sfc            ;
wire   [5:0]        wv_pkt_inport_fmj2sfc              ;

wire   [87:0]       wv_desp_cutthroughfwd_fmj2fifo     ;
wire                w_desp_wr_cutthroughfwd_fmj2fifo   ;

wire   [87:0]       wv_desp_sfc2fifo     ;
wire                w_desp_wr_sfc2fifo   ;

wire                w_storedfwd_fifo_empty_fifo2dou;
wire                w_storedfwd_fifo_rd_dou2fifo;
wire   [87:0]       wv_storedfwd_fifo_rdata_fifo2dou;

wire                w_cutthroughfwd_fifo_empty_fifo2dou;
wire                w_cutthroughfwd_fifo_rd_dou2fifo;
wire   [87:0]       wv_cutthroughfwd_fifo_rdata_fifo2dou;

wire                w_storedfwd_wr   ;
wire                w_storedfwd_rd    ;
wire   [94:0]       wv_storedfwd_rdata; 
wire                w_storedfwd_empty ;

wire  [(NUM_XGMAC + NUM_GMAC + 1)  -1:0]              w_pkt_rx_finish_rd;
wire  [(NUM_XGMAC + NUM_GMAC + 1)  -1:0]              w_pkt_rx_finish_rdata; 
wire  [(NUM_XGMAC + NUM_GMAC + 1)  -1:0]              w_pkt_rx_finish_empty;
//`ifdef altera_ip
generate 
genvar i;
	for(i=0; i<=(NUM_XGMAC + NUM_GMAC + 1)  -1; i = i+1) begin: RX_FINISH_CACHE_GROUP
		syncfifo_showahead_sclr_w1d32 rx_finish_cache_inst(
			.data  (i_pkt_rx_finish[i]  ), 
			.wrreq (i_pkt_rx_finish[i]),
			.rdreq (w_pkt_rx_finish_rd[i]),
			.clock (i_clk),
			.aclr  (!i_rst_n), 
			.q     (w_pkt_rx_finish_rdata[i]),    
			.usedw (),
			.full  (), 
			.empty (w_pkt_rx_finish_empty[i]) 
		);
	end
endgenerate	
syncfifo_showahead_sclr_w95d32 storedfwd_cache_inst(
	.data  ({w_cutthroughfwd_fmj2sfc,wv_pkt_inport_fmj2sfc,wv_desp_storedfwd_fmj2sfc}), 
	.wrreq (w_desp_wr_storedfwd_fmj2sfc),
	.rdreq (w_storedfwd_rd),
	.clock (i_clk),
	.aclr  (!i_rst_n), 
	.q     (wv_storedfwd_rdata),    
	.usedw (),
	.full  (), 
	.empty (w_storedfwd_empty) 
);

tdpr_singleclock_rdenab_outputaclrab_w34d64 tdpr_singleclock_rdenab_outputaclrab_w34d64_inst(
.aclr                  (!i_rst_n),
                     
.address_a             (iv_fwdmoderam_addr),
.address_b             (wv_ram_raddr_b_fml2ram),
                      
.clock                 (i_clk),
                       
.data_a                (iv_fwdmoderam_wdata),
.data_b                (34'h0),
                      
.rden_a                (i_fwdmoderam_rd),
.rden_b                (w_ram_rd_b_fml2ram),
                     
.wren_a                (i_fwdmoderam_wr),
.wren_b                (1'b0),
                       
.q_a                   (ov_fwdmoderam_rdata),
.q_b                   (wv_ram_rdata_b_ram2fml)
);

syncfifo_showahead_sclr_w88d16 storedfwd_desp_cache_inst(
	.data  (wv_desp_sfc2fifo), 
	.wrreq (w_desp_wr_sfc2fifo),
	.rdreq (w_storedfwd_fifo_rd_dou2fifo),
	.clock (i_clk),
	.aclr  (!i_rst_n), 
	.q     (wv_storedfwd_fifo_rdata_fifo2dou),    
	.usedw (),
	.full  (), 
	.empty (w_storedfwd_fifo_empty_fifo2dou) 
);

syncfifo_showahead_sclr_w88d16 cutthroughfwd_desp_cache_inst(
	.data  (wv_desp_cutthroughfwd_fmj2fifo), 
	.wrreq (w_desp_wr_cutthroughfwd_fmj2fifo),
	.rdreq (w_cutthroughfwd_fifo_rd_dou2fifo),
	.clock (i_clk),
	.aclr  (!i_rst_n), 
	.q     (wv_cutthroughfwd_fifo_rdata_fifo2dou),    
	.usedw (),
	.full  (), 
	.empty (w_cutthroughfwd_fifo_empty_fifo2dou) 
);

//`endif
`ifdef xilinx_ip
generate 
genvar i;
	for(i=0; i<=(NUM_XGMAC + NUM_GMAC + 1)  -1; i = i+1) begin: RX_FINISH_CACHE_GROUP
		syncfifo_showahead_sclr_w1d32 rx_finish_cache_inst(
			.srst      (!i_rst_n),                    //Reset the all signal
			.din       (i_pkt_rx_finish[i]),                       //The Inport of data 
			.rd_en     (w_pkt_rx_finish_rd[i]),       //active-high
			.clk       (i_clk),                       //ASYNC WriteClk(), SYNC use wrclk
			.wr_en     (i_pkt_rx_finish[i]),                     //active-high
			.dout      (w_pkt_rx_finish_rdata[i]),   //The output of data
			.full      (),                            //Write domain full 
			.empty     (w_pkt_rx_finish_empty[i]),    //Write domain empty
			.data_count()                            //Read-usedword
			);
	end
endgenerate

syncfifo_showahead_sclr_w95d32 storedfwd_cache_inst(
.srst      (!i_rst_n),                    //Reset the all signal
.din       ({w_cutthroughfwd_fmj2sfc,wv_pkt_inport_fmj2sfc,wv_desp_storedfwd_fmj2sfc}),                       //The Inport of data 
.rd_en     (w_storedfwd_rd),       //active-high
.clk       (i_clk),                       //ASYNC WriteClk(), SYNC use wrclk
.wr_en     (w_desp_wr_storedfwd_fmj2sfc),                     //active-high
.dout      (wv_storedfwd_rdata),   //The output of data
.full      (),                            //Write domain full 
.empty     (w_storedfwd_empty),    //Write domain empty
.data_count()                            //Read-usedword
);
truedualportram_singleclock_rdenab_outputaclrab_w34d64 truedualportram_singleclock_rdenab_outputaclrab_w34d64_inst(
.rsta                         (!i_rst_n),
.rstb                         (!i_rst_n),
.regcea                       (1'b1),
.regceb                       (1'b1),
     
.addra                        (iv_fwdmoderam_addr),
.addrb                        (wv_ram_raddr_b_fml2ram),
.clka                         (i_clk),
.clkb                         (i_clk),     
.dina                         (iv_fwdmoderam_wdata),
.dinb                         (34'h0),                             
.ena                          (1'b1),
.enb                          (1'b1),                            
.wea                          (i_fwdmoderam_wr),
.web                          (1'b0),                        
.douta                        (ov_fwdmoderam_rdata),
.doutb                        (wv_ram_rdata_b_ram2fml)
);

syncfifo_showahead_sclr_w88d16 storedfwd_desp_cache_inst(
.srst      (!i_rst_n),                    //Reset the all signal
.din       (wv_desp_sfc2fifo),                       //The Inport of data 
.rd_en     (w_storedfwd_fifo_rd_dou2fifo),       //active-high 
.clk       (i_clk),                       //ASYNC WriteClk(), SYNC use wrclk   
.wr_en     (w_desp_wr_sfc2fifo),                     //active-high                    
.dout      (wv_storedfwd_fifo_rdata_fifo2dou),   //The output of data
.full      (),                            //Write domain full 
.empty     (w_storedfwd_fifo_empty_fifo2dou),    //Write domain empty
.data_count()                            //Read-usedword
);

syncfifo_showahead_sclr_w88d16 cutthroughfwd_desp_cache_inst(
.srst      (!i_rst_n),                    //Reset the all signal
.din       (wv_desp_cutthroughfwd_fmj2fifo),                       //The Inport of data 
.rd_en     (w_cutthroughfwd_fifo_rd_dou2fifo),       //active-high
.clk       (i_clk),                       //ASYNC WriteClk(), SYNC use wrclk
.wr_en     (w_desp_wr_cutthroughfwd_fmj2fifo),                     //active-high
.dout      (wv_cutthroughfwd_fifo_rdata_fifo2dou),   //The output of data
.full      (),                            //Write domain full 
.empty     (w_cutthroughfwd_fifo_empty_fifo2dou),    //Write domain empty
.data_count()                            //Read-usedword
);
`endif

forward_mode_lookup forward_mode_lookup_inst
(
.i_clk         (i_clk       ),
.i_rst_n       (i_rst_n     ),
                
.iv_desp       (iv_desp     ),
.i_desp_wr     (i_desp_wr   ),
                
.ov_ram_raddr  (wv_ram_raddr_b_fml2ram),
.o_ram_rd      (w_ram_rd_b_fml2ram    ),
                
.ov_desp       (wv_desp_fml2fmj     ),
.o_desp_wr     (w_desp_wr_fml2fmj   )
);

forward_mode_judge forward_mode_judge_inst
(
.i_clk                   (i_clk                  ),
.i_rst_n                 (i_rst_n                ),
                          
.iv_desp                 (wv_desp_fml2fmj                   ),  
.i_desp_wr               (w_desp_wr_fml2fmj                 ),  
                          
.iv_ram_rdata            (wv_ram_rdata_b_ram2fml            ),
                          
.ov_desp_storedfwd       (wv_desp_storedfwd_fmj2sfc       ),
.o_desp_wr_storedfwd     (w_desp_wr_storedfwd_fmj2sfc     ),
.o_cutthroughfwd         (w_cutthroughfwd_fmj2sfc),
.ov_pkt_inport           (wv_pkt_inport_fmj2sfc  ),

.ov_desp_cutthroughfwd   (wv_desp_cutthroughfwd_fmj2fifo  ),
.o_desp_wr_cutthroughfwd (w_desp_wr_cutthroughfwd_fmj2fifo)   
);

stored_forward_control 
#(
    .NUM_GMAC(NUM_GMAC)
   ,.NUM_XGMAC(NUM_XGMAC)
)
stored_forward_control_inst
(
.i_clk              (i_clk              ),
.i_rst_n            (i_rst_n            ),

.i_pkt_rx_finish_empty (w_pkt_rx_finish_empty ),
.o_pkt_rx_finish_rd    (w_pkt_rx_finish_rd    ),
.i_pkt_rx_finish_rdata (w_pkt_rx_finish_rdata ),
                          
//.i_pkt_rx_finish_empty_p1 (w_pkt_rx_finish_empty_p1 ),
//.o_pkt_rx_finish_rd_p1    (w_pkt_rx_finish_rd_p1    ),
//.i_pkt_rx_finish_rdata_p1 (w_pkt_rx_finish_rdata_p1 ),
//                          
//.i_pkt_rx_finish_empty_p2 (w_pkt_rx_finish_empty_p2 ),
//.o_pkt_rx_finish_rd_p2    (w_pkt_rx_finish_rd_p2    ),
//.i_pkt_rx_finish_rdata_p2 (w_pkt_rx_finish_rdata_p2 ),
//                          
//.i_pkt_rx_finish_empty_p3 (w_pkt_rx_finish_empty_p3 ),
//.o_pkt_rx_finish_rd_p3    (w_pkt_rx_finish_rd_p3    ),
//.i_pkt_rx_finish_rdata_p3 (w_pkt_rx_finish_rdata_p3 ),
//                          
//.i_pkt_rx_finish_empty_p4 (w_pkt_rx_finish_empty_p4 ),
//.o_pkt_rx_finish_rd_p4    (w_pkt_rx_finish_rd_p4    ),
//.i_pkt_rx_finish_rdata_p4 (w_pkt_rx_finish_rdata_p4 ),
//                          
//.i_pkt_rx_finish_empty_p5 (w_pkt_rx_finish_empty_p5 ),
//.o_pkt_rx_finish_rd_p5    (w_pkt_rx_finish_rd_p5    ),
//.i_pkt_rx_finish_rdata_p5 (w_pkt_rx_finish_rdata_p5 ),
//                          
//.i_pkt_rx_finish_empty_p6 (w_pkt_rx_finish_empty_p6 ),
//.o_pkt_rx_finish_rd_p6    (w_pkt_rx_finish_rd_p6    ),
//.i_pkt_rx_finish_rdata_p6 (w_pkt_rx_finish_rdata_p6 ),
//                          
//.i_pkt_rx_finish_empty_p7 (w_pkt_rx_finish_empty_p7 ),
//.o_pkt_rx_finish_rd_p7    (w_pkt_rx_finish_rd_p7    ),
//.i_pkt_rx_finish_rdata_p7 (w_pkt_rx_finish_rdata_p7 ),
//                          
//.i_pkt_rx_finish_empty_p8 (w_pkt_rx_finish_empty_p8 ),
//.o_pkt_rx_finish_rd_p8    (w_pkt_rx_finish_rd_p8    ),
//.i_pkt_rx_finish_rdata_p8 (w_pkt_rx_finish_rdata_p8 ),
//                          
//.i_pkt_rx_finish_empty_p9 (w_pkt_rx_finish_empty_p9 ),
//.o_pkt_rx_finish_rd_p9    (w_pkt_rx_finish_rd_p9    ),
//.i_pkt_rx_finish_rdata_p9 (w_pkt_rx_finish_rdata_p9 ),
//
//.i_pkt_rx_finish_empty_p10(w_pkt_rx_finish_empty_p10 ),
//.o_pkt_rx_finish_rd_p10   (w_pkt_rx_finish_rd_p10    ),
//.i_pkt_rx_finish_rdata_p10(w_pkt_rx_finish_rdata_p10 ),
//
//.i_pkt_rx_finish_empty_p11(w_pkt_rx_finish_empty_p11 ),
//.o_pkt_rx_finish_rd_p11   (w_pkt_rx_finish_rd_p11    ),
//.i_pkt_rx_finish_rdata_p11(w_pkt_rx_finish_rdata_p11 ),
//
//.i_pkt_rx_finish_empty_p12(w_pkt_rx_finish_empty_p12 ),
//.o_pkt_rx_finish_rd_p12   (w_pkt_rx_finish_rd_p12    ),
//.i_pkt_rx_finish_rdata_p12(w_pkt_rx_finish_rdata_p12 ),
//
//.i_pkt_rx_finish_empty_p13(w_pkt_rx_finish_empty_p13 ),
//.o_pkt_rx_finish_rd_p13   (w_pkt_rx_finish_rd_p13    ),
//.i_pkt_rx_finish_rdata_p13(w_pkt_rx_finish_rdata_p13 ),
//
//.i_pkt_rx_finish_empty_p14(w_pkt_rx_finish_empty_p14 ),
//.o_pkt_rx_finish_rd_p14   (w_pkt_rx_finish_rd_p14    ),
//.i_pkt_rx_finish_rdata_p14(w_pkt_rx_finish_rdata_p14 ),
//
//.i_pkt_rx_finish_empty_p15(w_pkt_rx_finish_empty_p15 ),
//.o_pkt_rx_finish_rd_p15   (w_pkt_rx_finish_rd_p15    ),
//.i_pkt_rx_finish_rdata_p15(w_pkt_rx_finish_rdata_p15 ),
//
//.i_pkt_rx_finish_empty_p16(w_pkt_rx_finish_empty_p16 ),
//.o_pkt_rx_finish_rd_p16   (w_pkt_rx_finish_rd_p16    ),
//.i_pkt_rx_finish_rdata_p16(w_pkt_rx_finish_rdata_p16 ),
//
//.i_pkt_rx_finish_empty_p17(w_pkt_rx_finish_empty_p17 ),
//.o_pkt_rx_finish_rd_p17   (w_pkt_rx_finish_rd_p17    ),
//.i_pkt_rx_finish_rdata_p17(w_pkt_rx_finish_rdata_p17 ),
//
//.i_pkt_rx_finish_empty_p18(w_pkt_rx_finish_empty_p18 ),
//.o_pkt_rx_finish_rd_p18   (w_pkt_rx_finish_rd_p18    ),
//.i_pkt_rx_finish_rdata_p18(w_pkt_rx_finish_rdata_p18 ),
//
//.i_pkt_rx_finish_empty_p19(w_pkt_rx_finish_empty_p19 ),
//.o_pkt_rx_finish_rd_p19   (w_pkt_rx_finish_rd_p19    ),
//.i_pkt_rx_finish_rdata_p19(w_pkt_rx_finish_rdata_p19 ),
//
//.i_pkt_rx_finish_empty_p20(w_pkt_rx_finish_empty_p20 ),
//.o_pkt_rx_finish_rd_p20   (w_pkt_rx_finish_rd_p20    ),
//.i_pkt_rx_finish_rdata_p20(w_pkt_rx_finish_rdata_p20 ),
//
//.i_pkt_rx_finish_empty_p21(w_pkt_rx_finish_empty_p21 ),
//.o_pkt_rx_finish_rd_p21   (w_pkt_rx_finish_rd_p21    ),
//.i_pkt_rx_finish_rdata_p21(w_pkt_rx_finish_rdata_p21 ),
//
//.i_pkt_rx_finish_empty_p22(w_pkt_rx_finish_empty_p22 ),
//.o_pkt_rx_finish_rd_p22   (w_pkt_rx_finish_rd_p22    ),
//.i_pkt_rx_finish_rdata_p22(w_pkt_rx_finish_rdata_p22 ),
//
//.i_pkt_rx_finish_empty_p23(w_pkt_rx_finish_empty_p23 ),
//.o_pkt_rx_finish_rd_p23   (w_pkt_rx_finish_rd_p23    ),
//.i_pkt_rx_finish_rdata_p23(w_pkt_rx_finish_rdata_p23 ),
//
//.i_pkt_rx_finish_empty_p24(w_pkt_rx_finish_empty_p24 ),
//.o_pkt_rx_finish_rd_p24   (w_pkt_rx_finish_rd_p24    ),
//.i_pkt_rx_finish_rdata_p24(w_pkt_rx_finish_rdata_p24 ),
//
//.i_pkt_rx_finish_empty_p25(w_pkt_rx_finish_empty_p25 ),
//.o_pkt_rx_finish_rd_p25   (w_pkt_rx_finish_rd_p25    ),
//.i_pkt_rx_finish_rdata_p25(w_pkt_rx_finish_rdata_p25 ),
//
//.i_pkt_rx_finish_empty_p26(w_pkt_rx_finish_empty_p26 ),
//.o_pkt_rx_finish_rd_p26   (w_pkt_rx_finish_rd_p26    ),
//.i_pkt_rx_finish_rdata_p26(w_pkt_rx_finish_rdata_p26 ),
//
//.i_pkt_rx_finish_empty_p27(w_pkt_rx_finish_empty_p27 ),
//.o_pkt_rx_finish_rd_p27   (w_pkt_rx_finish_rd_p27    ),
//.i_pkt_rx_finish_rdata_p27(w_pkt_rx_finish_rdata_p27 ),
//
//.i_pkt_rx_finish_empty_p28(w_pkt_rx_finish_empty_p28 ),
//.o_pkt_rx_finish_rd_p28   (w_pkt_rx_finish_rd_p28    ),
//.i_pkt_rx_finish_rdata_p28(w_pkt_rx_finish_rdata_p28 ),
//
//.i_pkt_rx_finish_empty_p29(w_pkt_rx_finish_empty_p29 ),
//.o_pkt_rx_finish_rd_p29   (w_pkt_rx_finish_rd_p29    ),
//.i_pkt_rx_finish_rdata_p29(w_pkt_rx_finish_rdata_p29 ),
//
//.i_pkt_rx_finish_empty_p30(w_pkt_rx_finish_empty_p30 ),
//.o_pkt_rx_finish_rd_p30   (w_pkt_rx_finish_rd_p30    ),
//.i_pkt_rx_finish_rdata_p30(w_pkt_rx_finish_rdata_p30 ),
//
//.i_pkt_rx_finish_empty_p31(w_pkt_rx_finish_empty_p31 ),
//.o_pkt_rx_finish_rd_p31   (w_pkt_rx_finish_rd_p31    ),
//.i_pkt_rx_finish_rdata_p31(w_pkt_rx_finish_rdata_p31 ),
//
//.i_pkt_rx_finish_empty_p32(w_pkt_rx_finish_empty_p32 ),
//.o_pkt_rx_finish_rd_p32   (w_pkt_rx_finish_rd_p32    ),
//.i_pkt_rx_finish_rdata_p32(w_pkt_rx_finish_rdata_p32 ),

//.iv_desp            (wv_desp_storedfwd_fmj2sfc            ),  
//.i_desp_wr          (w_desp_wr_storedfwd_fmj2sfc          ), 
//.i_cutthroughfwd    (w_cutthroughfwd_fmj2sfc),
//.iv_pkt_inport      (wv_pkt_inport_fmj2sfc  ),

.o_storedfwd_rd     (w_storedfwd_rd         ),
.iv_storedfwd_rdata (wv_storedfwd_rdata     ),
.i_storedfwd_empty  (w_storedfwd_empty      ),

.ov_desp            (wv_desp_sfc2fifo            ),
.o_desp_wr          (w_desp_wr_sfc2fifo          )
);

descriptor_output descriptor_output_inst
(
.i_clk                       (i_clk                      ),
.i_rst_n                     (i_rst_n                    ),
                              
.i_storedfwd_fifo_empty      (w_storedfwd_fifo_empty_fifo2dou     ),
.o_storedfwd_fifo_rd         (w_storedfwd_fifo_rd_dou2fifo        ),
.iv_storedfwd_fifo_rdata     (wv_storedfwd_fifo_rdata_fifo2dou    ),
                              
.i_cutthroughfwd_fifo_empty  (w_cutthroughfwd_fifo_empty_fifo2dou ),
.o_cutthroughfwd_fifo_rd     (w_cutthroughfwd_fifo_rd_dou2fifo    ),
.iv_cutthroughfwd_fifo_rdata (wv_cutthroughfwd_fifo_rdata_fifo2dou),       
                              
.ov_desp                     (ov_desp                    ),
.o_desp_wr                   (o_desp_wr                  )
);
endmodule           